<!--
 * @Description: 防抖节流
 * @Author: chenjiaxin
 * @Date: 2022-02-20 16:34:53
 * @LastEditTime: 2022-02-24 13:39:22
 * @FilePath: \super-unit\test\index3.html
-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>防抖节流</title>
  </head>
  <body>
    <div>
      <h2>防抖</h2>
      <input type="text" id="my-input" />
      <button id="cancel">取消</button>
      <h2>节流</h2>
      <input type="text" id="throttle" />
      <button id="throttle_cancel">取消</button>
    </div>

    <script>
      /**
       * immediate: 是否立即执行
       */
      function debounce(fn, delay = 1000, immediate = false, callbackFn) {
        let timeId = null;
        let isExecute = false; //是否执行过
        let firstTimer = null;
        function newFn(...args) {
          if (immediate && !isExecute) {
            //===>>>要立即执行
            fn.apply(this, args);
            isExecute = true;
            // 处理 返回值
            if (callbackFn && typeof callbackFn === "function") {
              callbackFn("接收的返回值");
            }
            firstTimer = setTimeout(() => {
              isExecute = false;
            }, delay);
          } else {
            //===>>>不要立即执行
            if (firstTimer) clearTimeout(firstTimer);
            if (timeId) clearTimeout(timeId);
            timeId = setTimeout(() => {
              // fn();
              fn.apply(this, args);
              isExecute = false;
              timeId = null;
              // 处理 返回值
              if (callbackFn && typeof callbackFn === "function") {
                callbackFn("接收的返回值");
              }
            }, delay);
          }
        }
        newFn.cancel = function () {
          if (timeId) {
            clearTimeout(timeId);
            isExecute = false;
            timeId = null;
          }
        };
        return newFn;
      }
      /**
       * 节流
       * leading: true 第一次是否触发
       * traling: false 最后一次 没有到时间 是否要执行
       */
      function throttle(fn, interval = 1000, options = { leading: true, traling: false, callbackFn: null }) {
        let lastTime = 0;
        let { leading, traling, callbackFn } = options;
        let timeId = null;
        function newThrottle(...args) {
          let rowTime = new Date().getTime();
          if (!leading && !lastTime) {
            //不要第一次触发 并且 lastTime 为false 的时候，把 lastTime 赋值 为 当前时间。这样第一次就不会触发了
            lastTime = rowTime;
          }
          // 执行条件 rowTime - lastTime >= interval 就是要去执行 触发函数
          let spaceTime = interval - (rowTime - lastTime);
          if (spaceTime <= 0) {
            //要执行
            // fn();
            fn.apply(this, args);
            lastTime = rowTime;
            if (typeof callbackFn === "function") callbackFn("执行参数");
            return;
          }
          //时间还没有到
          if (traling) {
            if (timeId) clearTimeout(timeId);
            timeId = setTimeout(() => {
              // fn();
              fn.apply(this, args);
              lastTime = new Date().getTime();
              timeId = null;
              if (typeof callbackFn === "function") callbackFn("执行参数");
            }, spaceTime);
          }
        }
        //取消功能
        newThrottle.cancle = function () {
          if (timeId) clearTimeout(timeId);
        };
        return newThrottle;
      }
    </script>
    <script>
      let inputEle = document.querySelector("#my-input");
      let count = 0;
      function inputChange(event) {
        count++;
        console.log("发送请求", count, this, event);
      }
      // let newInputChange = debounce(inputChange);
      // inputEle.addEventListener("input", inputChange);
      // inputEle.addEventListener("input", newInputChange);

      //立即执行，开始后立即执行请求一次
      // let newInputChange = debounce(inputChange, 1000, true);
      // inputEle.addEventListener("input", newInputChange);
      //===>>>取消功能
      // let cancelEle = document.querySelector("#cancel");
      // let newInputChange = debounce(inputChange, 2000, true);
      // inputEle.addEventListener("input", newInputChange);
      // cancelEle.addEventListener("click", newInputChange.cancel);
      //===>>>拿到返回值
      //1、传一个回调函数
      //2、debounce函数返回一个Promise
      function callbackFn(res) {
        console.log(res);
      }
      let newInputChange = debounce(inputChange, 1000, true, callbackFn);
      inputEle.addEventListener("input", newInputChange);
    </script>
    <script>
      let throttleEle = document.querySelector("#throttle");
      let throttleCancelEle = document.querySelector("#throttle_cancel");
      let num = 0;
      function inputHandle(event) {
        num++;
        console.log("发送请求", num, this, event);
      }
      // let newInputHandle = throttle(inputHandle, 1000);
      // throttleEle.addEventListener("input", newInputHandle);
      //第一次是否 执行
      // let newInputHandle = throttle(inputHandle, 1000, false);
      // throttleEle.addEventListener("input", newInputHandle);

      //最后一次时间没有到是否要执行
      // let newInputHandle = throttle(inputHandle, 2000, {
      //   leading: true,
      //   traling: true,
      // });
      // throttleEle.addEventListener("input", newInputHandle);
      //4、取消功能 及回调函数
      let newInputHandle = throttle(inputHandle, 2000, {
        leading: false,
        traling: true,
        callbackFn: function (params) {
          console.log("参数", params);
        }
      });
      throttleEle.addEventListener("input", newInputHandle);
      throttleCancelEle.addEventListener("click", newInputHandle.cancle);
      //5、回调函数
    </script>
  </body>
</html>
